<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>非对称加密与对称加密</title>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jsencrypt/2.3.1/jsencrypt.min.js"></script>
</head>

<body>

    <br />
    传送数据：<input id="msg"/>
    <br />

    <button onclick="onSubmit()">测试</button>

    <script>

    var publicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxx49RIaiSMlP5o9EuaDl
ga0NmZ7KYWsdvQJSrBT5YHhdkNF3B2SrfTi//pwA8CTYcv8kj2GGtpiw+4ipT0Xf
ptuojxCJV/+2sUc2K0Bb+CrLGaltM/Umj+JPfHQeA6D8DstDl4ozw+7HbwpwcFNL
6H1vBO5C0FamsEsVme6hYqzY5fAI9nInOjd0aWEomntNYIfQAO1Dpji11ISFxjNB
HAaOMZwyPVWzfM0YdfaNNnw/q+HdRjGO5O5ZxD2AxhYREgs/Mh+y0OilpqMlCpge
hAvDt7pQ4N+rqvSFotp+/tdXAhkiHrPaZmU6TibAwEnwolZw1Lz1FMm4MEAF1YCF
GQIDAQAB
-----END PUBLIC KEY-----`;



        function randomWord(length, firstChar) {
            var arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
            var str = "";
            for (var i = 0; i < length; i++) {
                var pos;
                if(firstChar) {
                    pos = Math.round(Math.random() * (arr.length - 11) + 10);
                } else {
                    pos = Math.round(Math.random() * (arr.length - 1));
                }
                str += arr[pos];
            }
            return str;
        }

        function onSubmit() {

            var mInput = document.getElementById('msg');

            // 1.组织传送的数据
            var msg = mInput.value;

            // 2.生成AES的密钥和向量
            var aesKey = randomWord(16, true);
            var aesIv = randomWord(16, true);

            // 3.将AES使用RSA加密
            var jsEncrypt = new JSEncrypt();
            jsEncrypt.setPublicKey(publicKey);
            var key = jsEncrypt.encrypt(JSON.stringify({key: aesKey, iv: aesIv}));

            // 4. 使用AES将数据加密
            // 注意这里使用的是CBC模式，有密钥和向量，Pkcs7的填充模式，前后端需要一致
            var aesEncrypt = CryptoJS.AES.encrypt(msg, CryptoJS.enc.Utf8.parse(aesKey), {
                iv: CryptoJS.enc.Utf8.parse(aesIv),
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7
            });
            var data =  aesEncrypt.toString();

            // 5. 发送参数到后端
            var formData = new FormData();
            formData.append('key', key);
            formData.append('data', data);

            axios.post('http://127.0.0.1:3000/test', formData).then((res) => {
                var resData = res.data;
                if(resData.code == 0) {
                    const decrypt = CryptoJS.AES.decrypt(resData.data, CryptoJS.enc.Utf8.parse(aesKey), {
                        iv: CryptoJS.enc.Utf8.parse(aesIv),
                        mode: CryptoJS.mode.CBC,
                        padding: CryptoJS.pad.Pkcs7
                    });
                    const msg = CryptoJS.enc.Utf8.stringify(decrypt);  
                    alert(msg);
                } else {
                    alert(resData.msg);
                }
            }).catch((error) => {
                alert('error');
            });
        }
    </script>
</body>

</html>